/**
 *遇到#表示是表达式
 *遇到字符表示变量
 */
String.prototype.render = function (data) {
    //? 正则表达式  /{{[\s\S]*?}}/g  来匹配所有  {}  之间的字符串， [\s\S]*?  表示可以匹配任意字符(其中  \s  表示匹配任意空白字符（包括空格和制表符）， \S  表示匹配任意非空白字符,  *?  表示尽可能少地匹配所有字符)， g  表示全局匹配
    //? 例如，当输入字符串为  Hello {{name}}! ，则匹配到的字符串为  {{name}} 。由于指定了g全局匹配 所以replace函数会多次执行直到所有匹配项都被替换
    //? 第一个参数是匹配模式，可以是一个字符串或正则表达式。如果是一个字符串，表示需要查找被替换的子字符串；如果是一个正则表达式，它将用来匹配需要替换的字符串部分，并将其作为第二个参数中指定的替换字符串的目标。
    //? replace第二个参数是替换字符串，用于替换匹配到的子字符串的部分。可以是一个字符串或函数。如果是字符串，则所有匹配到的子字符串都将被替换为该字符串；如果是函数，则可以根据匹配到的子字符串动态生成替换字符串。
    return this.replace(/{{[\s\S]*?}}/g, match => {
        //? slice去掉两边括号 trim去掉空格和换行符 也就是拿到了{{xxx}}里的xxx
        match = match.slice(2, match.length - 2).trim();
        //? 为空
        if (match === "") {
            return;
        } else if (match[0] === '#') {
            //? #后所有字符串执行eval函数
            //? eval()  函数是 JavaScript 的一个全局函数，它接受一个参数，该参数可以是一个字符串，也可以是一个函数。
            //? 当参数为字符串时， eval()  函数会将这个字符串作为代码来执行，返回执行结果；当参数为函数时， eval()  函数会将函数转换为字符串，然后按照字符串的方式执行
            return eval(match.slice(1));
        } else {
            // ? 不空也不是表达式
            return data[match] || '';
        }
    })
}
const data = {
    name: "小明",
    age: 22,
    school: "第三中学",
    classroom: "教室2"
}


console.log(
    "{{ name }} 今年 {{ age }} 岁，就读于 {{ school }} 今天在 {{ classroom }} 上课，{{ name }} {{ #data.age >= 18 ? '成年了' : '未成年' }}".render(data)
);
// 小明 今年 16 岁，就读于 第三中学 今天在 教室2 上课，小明 未成年

console.log(
    `{{name}}说了句{{#
        if (data.age >= 18) {
            "我已经成年了！"
        } else {
            "我还没有成年！"
        }
    }}`.render(data)
);
// 小明说了句我还没有成年！
